package com.google.code.jira.script.service;

import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.Iterator;
import java.util.List;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import org.apache.commons.io.IOUtils;
import org.apache.log4j.Category;

import com.atlassian.configurable.ObjectConfiguration;
import com.atlassian.configurable.ObjectConfigurationException;
import com.atlassian.jira.service.AbstractService;
import com.opensymphony.module.propertyset.PropertySet;

public class ScriptService extends AbstractService {

	private static final Category log = Category.getInstance(ScriptService.class);

	private static final String SERVICE_ID = ScriptService.class.getName();

	private static final String SERVICE_XML = "service/scriptservice.xml";

	private static final String INPUT_FILE_KEY = "FILE";

	private static final String ENGINE_NAME_KEY = "ENGINE";

	private String inputFile;

	private String engineName;

	public ObjectConfiguration getObjectConfiguration() throws ObjectConfigurationException {
		return getObjectConfiguration(SERVICE_ID, SERVICE_XML, null);
	}

	public void init(PropertySet ps) throws ObjectConfigurationException {
		super.init(ps);
		inputFile = getProperty(INPUT_FILE_KEY);
		engineName = getProperty(ENGINE_NAME_KEY);
		log.info("init: " + getName() + " - " + engineName + " - " + inputFile);
	}

	public void run() {
		log.info("run: " + getName() + " located at " + inputFile + " using " + engineName + " as engine.");

		// Validates "engineName" property
		if (engineName == null || "".equals(engineName)) {
			log.error("Skip running service because engine name is NULL!");
			return;
		}

		// Validates "inputFile" property
		if (inputFile == null || "".equals(inputFile)) {
			log.error("Skip running service because input file is NULL!");
			return;
		}

		// Loads the engine
		ScriptEngineManager manager = new ScriptEngineManager();
		List factories = manager.getEngineFactories();
		if (factories == null || factories.size() == 0) {
			log.error("No engines found! Please check your JVM version and configuration.");
		}

		ScriptEngine engine = null;
		for (Iterator iterator = factories.iterator(); iterator.hasNext();) {
			ScriptEngineFactory factory = (ScriptEngineFactory) iterator.next();
			if (engineName.equals(factory.getEngineName())) {
				engine = factory.getScriptEngine();
				break;
			}
		}

		if (engine == null) {
			log.error("No script engine found associate with the name " + engineName + ".");
		}

		Reader reader = null;
		try {
			engine.put("log", log);

			reader = new FileReader(inputFile);
			engine.eval(reader);
		} catch (ScriptException e) {
			log.error("Error evaluating script.", e);
		} catch (IOException e) {
			log.error("Error loading file.", e);
		} finally {
			IOUtils.closeQuietly(reader);
		}
	}
}